package com.zhaoyuxi.util;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by sunjian on 2018/7/12.
 */
public class RedPacketUtil {

    public enum RedPacket {
        MINMONEY(0.01f, "红包最小金额"),
        TOTAL_MONEY(10f, "红包总金额"),
        MAXMONEY(RedPacket.TOTAL_MONEY.getValue() * 0.9f, "单个红包最大金额"),
        RED_PACKET_COUNT(5f, "红包个数"),
        ROB_RED_PACKET_COUT(20, "发送包抢红包次数"),
        ROB_RED_PACKET_COUT_MAX(ROB_RED_PACKET_COUT.getValue() * 0.3f, "单个用户抢最大红包次数不得超过30%");
        private float value;
        private String key;

        public float getValue() {
            return value;
        }

        public String getKey() {
            return key;
        }

        RedPacket(float v, String k) {
            value = v;
            key = k;
        }
    }

    public static void main(String[] args) throws IOException {
        RedPacketUtil util = new RedPacketUtil();
        for (int i = 0; i < 20; i++) {
            System.out.println(RedPacketUtil.splitRedPackets(RedPacket.TOTAL_MONEY.getValue(), (int) RedPacket.RED_PACKET_COUNT.getValue()));
        }
    }

    /**
     * 平均分配金额算法
     *
     * @param money 总金额
     * @param count 红包个数
     * @return
     */
    public static boolean isRight(float money, int count) {
        // 如果平均红包值小于 最小值 0.01 大于红包最大值  总金额的90% 则重新分配
        double avg = money / count;
        if (avg < RedPacket.MINMONEY.getValue()) {
            return false;
        } else if (avg > money * 0.8) {
            return false;
        }
        return true;
    }

    /**
     * 随机产生单个红包金额
     *
     * @param money 总金额
     * @param mins  最小红包金额
     * @param maxs  单个红包最大值
     * @param count 红包个数
     * @return
     */
    public static float randomRedPacket(float money, float mins, float maxs, int count) {
        //如果是单个红包的话则直接分配
        if (count == 1 || count == money) {
            return (float) (Math.round(money * 100)) / 100;
        }
        //如果最大红包和最小红包一致则返回最小红包
        if (mins == maxs) {
            return mins;//如果最大值和最小值一样，就返回mins
        }
        float one = ((float) Math.random() * (money - mins) + mins);
        one = (float) (Math.round(one * 100)) / 100;
        float moneyOther = money - one;
        if (isRight(moneyOther, count - 1)) {
            return one;
        } else {
            //重新分配
            float avg = moneyOther / (count - 1);
            if (avg < RedPacket.MINMONEY.getValue()) {
                return randomRedPacket(money, mins, one, count);
            } else if (avg > money * 0.8) {
                return randomRedPacket(money, one, maxs, count);
            }
        }
        return one;
    }


    /**
     * 分配红包
     *
     * @param money 红包总金额
     * @param count 红包个数
     * @return
     */
    public static List<Float> splitRedPackets(float money, int count) {
        List<Float> list = new ArrayList<Float>();
        if (!isRight(money, count)) {
            return null;
        }
        for (int i = 0; i < count; i++) {
            float one = randomRedPacket(money, RedPacket.MINMONEY.getValue(), RedPacket.MAXMONEY.getValue(), count - i);
            list.add(one);
            money -= one;
        }
        return list;

    }

}
